package com.ndp.fb.walle.permission;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.ndp.ec.core.UserService;
import com.ndp.fb.enums.ErrorType;
import com.ndp.fb.mq.api.producer.RocketMqProducerService;
import com.ndp.fb.rdb.api.FunctionRdbService;
import com.ndp.fb.rdb.model.Function;
import com.ndp.fb.rdb.model.RoleAuthority;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.util.ListUtil;
import com.ndp.fb.util.ThreadPool;
import com.ndp.fb.walle.business.RoleAuthorityService;
import com.ndp.fb.walle.controller.SysMonitorController;
import com.ndp.fb.walle.controller.UserController;
import com.ndp.fb.walle.model.vo.OutputResult;
import com.ndp.fb.walle.util.ResponseUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * Created by yeahmobi on 2015/6/8.
 */
@Aspect
@Component
public class PermissionAspect {
    @Autowired
    private PermissionValidation permissionValidation;

    @Reference
    private FunctionRdbService functionRdbService;

    @Reference
    private UserService userService;

    @Autowired
    RoleAuthorityService roleAuthorityService;

    @Autowired
    private RocketMqProducerService rocketMqProducerService;

    @Pointcut("execution(* com.ndp.fb.walle.controller..*.*(..))") //表示匹配com.ndp.fb.walle.controller.包及其子包下的所有方法
    private void allControllerMethod(){}

    @Around("allControllerMethod()")
    public Object doAccessCheck(ProceedingJoinPoint pjp) throws Throwable {

        HttpSession httpSession = permissionValidation.getSession();
        Object userObj = httpSession.getAttribute("user");
        //track user action
        sendUserAction((User)userObj,pjp.getTarget().getClass().getSimpleName(),pjp.getSignature().getName());
        boolean hasAuth = checkAuthority(pjp, userObj);
        if(!hasAuth)
            return notAccessPrivilege();

        if(permissionValidation.Validation(pjp.getTarget().getClass(),pjp.getSignature().getName(),pjp.getArgs())) {
            return pjp.proceed();
        }else{
            OutputResult outputResult = ResponseUtils.bulidOutputResult(ErrorType.UNAUTHORIZED_ACCESS, null);
            return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
        }
    }

    private boolean checkAuthority(ProceedingJoinPoint pjp, Object userObj) throws Throwable {
        boolean hasAuth=false;
        if(userObj != null){
            User user = (User) userObj;
            List<Long> roleIds = userService.getRoleByUser(user.getId());
            Function function = functionRdbService.getFunctionByClazzAndMethodName(pjp.getTarget().getClass().getName(),pjp.getSignature().getName());
            if(function != null && ListUtil.isNotEmpty(roleIds)){
                List<RoleAuthority> roleAuthorityList = roleAuthorityService.getAuthoritysByRole(roleIds);
                if(roleAuthorityList !=null){
                    for (RoleAuthority roleAuthority : roleAuthorityList) {
                        if( roleAuthority.getFunctionId().longValue() == function.getId().longValue()){
                            hasAuth= true;
                        }
                    }
                }
            }else{
                //没配置过的功能就放过
                hasAuth= true;
            }
        }else{
            //所有的系统类和用户类的Controller 放过
            if(pjp.getTarget().getClass()== SysMonitorController.class||
                    pjp.getTarget().getClass()== UserController.class)
                hasAuth= true;
        }
        return hasAuth;
    }

    private Object notAccessPrivilege() {
        OutputResult outputResult = ResponseUtils.bulidOutputResult(ErrorType.ACCOUNT_NOT_ACCESS_PRIVILEGE, null);
        return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
    }

    private void sendUserAction(User user,String controller,String func){
        String username="Raiders";
        String userOrg="Hacker";
        if(user!=null){
            username=user.getUsername();
            userOrg=String.valueOf(user.getOrgId());
        }
        UserActionTrack userActionTrack=new UserActionTrack(rocketMqProducerService,username,userOrg,controller,func);
        ThreadPool.execute(userActionTrack);
    }

}
